package com.kh.rationaldrugreview.dto;

import com.kh.rationaldrugreview.enums.RiskLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 处方风险评估响应
 * Prescription Risk Assessment Response
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class PrescriptionRiskAssessmentResponse {
    
    /**
     * 评估ID
     */
    private String assessmentId;
    
    /**
     * 评估状态
     */
    private AssessmentStatus status;
    
    /**
     * 综合风险等级
     */
    private RiskLevel overallRiskLevel;
    
    /**
     * 风险评分
     */
    private Integer riskScore;
    
    /**
     * 评估摘要
     */
    private String summary;
    
    /**
     * 风险项列表
     */
    private List<RiskItem> riskItems;
    
    /**
     * 临床建议
     */
    private List<ClinicalRecommendation> recommendations;
    
    /**
     * 风险统计
     */
    private RiskStatistics statistics;
    
    /**
     * 患者信息摘要
     */
    private String patientSummary;
    
    /**
     * 处方信息摘要
     */
    private String prescriptionSummary;
    
    /**
     * 评估详情
     */
    private AssessmentDetails details;
    
    /**
     * 评估时间
     */
    private LocalDateTime assessmentTime;
    
    /**
     * 评估耗时(毫秒)
     */
    private Long processingTimeMs;
    
    /**
     * 数据源信息
     */
    private String dataSource;
    
    /**
     * 版本信息
     */
    private String version;
    
    /**
     * 评估状态枚举
     */
    public enum AssessmentStatus {
        SUCCESS("评估成功"),
        PARTIAL_SUCCESS("部分成功"),
        WARNING("存在警告"),
        ERROR("评估失败");
        
        private final String description;
        
        AssessmentStatus(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    /**
     * 风险统计
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class RiskStatistics {
        private Integer totalRisks;
        private Integer criticalRisks;
        private Integer highRisks;
        private Integer mediumRisks;
        private Integer lowRisks;
        private Integer noRisks;
        
        private Map<String, Integer> risksByCategory;
        private Map<String, Integer> risksByDrug;
        
        private Boolean hasHighPriorityRisks;
        private Boolean requiresImmediateAction;
        
        /**
         * 计算风险分布百分比
         */
        public Map<RiskLevel, Double> getRiskDistribution() {
            if (totalRisks == 0) return Map.of();
            
            return Map.of(
                RiskLevel.CRITICAL, (criticalRisks * 100.0) / totalRisks,
                RiskLevel.HIGH, (highRisks * 100.0) / totalRisks,
                RiskLevel.MEDIUM, (mediumRisks * 100.0) / totalRisks,
                RiskLevel.LOW, (lowRisks * 100.0) / totalRisks
            );
        }
    }
    
    /**
     * 评估详情
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class AssessmentDetails {
        private List<String> checkedCategories;    // 已检查的类别
        private List<String> skippedCategories;    // 跳过的类别
        private Map<String, String> parameters;    // 评估参数
        private List<String> warnings;             // 警告信息
        private List<String> errors;               // 错误信息
        private Map<String, Object> metadata;      // 元数据
    }
    
    /**
     * 判断是否存在高风险
     */
    public boolean hasHighRisk() {
        return overallRiskLevel != null && 
               (overallRiskLevel == RiskLevel.CRITICAL || overallRiskLevel == RiskLevel.HIGH);
    }
    
    /**
     * 判断是否需要立即处理
     */
    public boolean requiresImmediateAction() {
        return overallRiskLevel == RiskLevel.CRITICAL ||
               (riskItems != null && riskItems.stream()
                   .anyMatch(RiskItem::requiresImmediateAction));
    }
    
    /**
     * 获取高风险项
     */
    public List<RiskItem> getHighRiskItems() {
        if (riskItems == null) return List.of();
        return riskItems.stream()
            .filter(RiskItem::isHighRisk)
            .collect(Collectors.toList());
    }
    
    /**
     * 获取强制性建议
     */
    public List<ClinicalRecommendation> getMandatoryRecommendations() {
        if (recommendations == null) return List.of();
        return recommendations.stream()
            .filter(ClinicalRecommendation::isMandatory)
            .collect(Collectors.toList());
    }
    
    /**
     * 按药物分组的风险项
     */
    public Map<String, List<RiskItem>> getRisksByDrug() {
        if (riskItems == null) return Map.of();
        return riskItems.stream()
            .filter(item -> item.getAffectedDrugs() != null && !item.getAffectedDrugs().isEmpty())
            .collect(Collectors.groupingBy(
                item -> String.join("、", item.getAffectedDrugs())
            ));
    }
    
    /**
     * 获取风险等级颜色
     */
    public String getRiskColor() {
        return overallRiskLevel != null ? overallRiskLevel.getColor() : "#6c757d";
    }
    
    /**
     * 生成风险报告摘要
     */
    public String generateExecutiveSummary() {
        StringBuilder summary = new StringBuilder();
        
        // 综合风险等级
        if (overallRiskLevel != null) {
            summary.append("综合风险等级：").append(overallRiskLevel.getChineseName());
        }
        
        // 风险统计
        if (statistics != null) {
            summary.append("，共发现 ").append(statistics.getTotalRisks()).append(" 项风险");
            
            if (statistics.getCriticalRisks() > 0) {
                summary.append("，其中极高风险 ").append(statistics.getCriticalRisks()).append(" 项");
            }
            if (statistics.getHighRisks() > 0) {
                summary.append("，高风险 ").append(statistics.getHighRisks()).append(" 项");
            }
        }
        
        // 处理建议
        if (requiresImmediateAction()) {
            summary.append("。建议立即处理风险项。");
        } else if (hasHighRisk()) {
            summary.append("。建议优先处理高风险项。");
        } else {
            summary.append("。建议关注中低风险项。");
        }
        
        return summary.toString();
    }
    
    /**
     * 创建成功响应
     */
    public static PrescriptionRiskAssessmentResponse success(
            String assessmentId,
            RiskLevel overallRisk,
            List<RiskItem> risks,
            List<ClinicalRecommendation> recommendations) {
        
        RiskStatistics stats = calculateStatistics(risks);
        
        return PrescriptionRiskAssessmentResponse.builder()
            .assessmentId(assessmentId)
            .status(AssessmentStatus.SUCCESS)
            .overallRiskLevel(overallRisk)
            .riskItems(risks)
            .recommendations(recommendations)
            .statistics(stats)
            .assessmentTime(LocalDateTime.now())
            .build();
    }
    
    /**
     * 计算风险统计
     */
    private static RiskStatistics calculateStatistics(List<RiskItem> riskItems) {
        if (riskItems == null || riskItems.isEmpty()) {
            return RiskStatistics.builder()
                .totalRisks(0)
                .criticalRisks(0)
                .highRisks(0)
                .mediumRisks(0)
                .lowRisks(0)
                .hasHighPriorityRisks(false)
                .requiresImmediateAction(false)
                .build();
        }
        
        Map<RiskLevel, Long> riskCounts = riskItems.stream()
            .collect(Collectors.groupingBy(
                RiskItem::getRiskLevel,
                Collectors.counting()
            ));
        
        return RiskStatistics.builder()
            .totalRisks(riskItems.size())
            .criticalRisks(riskCounts.getOrDefault(RiskLevel.CRITICAL, 0L).intValue())
            .highRisks(riskCounts.getOrDefault(RiskLevel.HIGH, 0L).intValue())
            .mediumRisks(riskCounts.getOrDefault(RiskLevel.MEDIUM, 0L).intValue())
            .lowRisks(riskCounts.getOrDefault(RiskLevel.LOW, 0L).intValue())
            .hasHighPriorityRisks(riskCounts.getOrDefault(RiskLevel.CRITICAL, 0L) > 0 ||
                                 riskCounts.getOrDefault(RiskLevel.HIGH, 0L) > 0)
            .requiresImmediateAction(riskCounts.getOrDefault(RiskLevel.CRITICAL, 0L) > 0)
            .build();
    }
}